package com.zhengshang.api.controller;

import com.zhengshang.common.annotation.Log;
import com.zhengshang.common.annotation.RepeatSubmit;
import com.zhengshang.common.constant.UserConstants;
import com.zhengshang.common.constant.app.AppConstant;
import com.zhengshang.common.core.controller.BaseController;
import com.zhengshang.common.core.domain.AjaxResult;
import com.zhengshang.common.core.domain.entity.SysRole;
import com.zhengshang.common.core.domain.entity.SysUser;
import com.zhengshang.common.core.domain.model.LoginAppUser;
import com.zhengshang.common.enums.BusinessType;
import com.zhengshang.common.enums.UserStatus;
import com.zhengshang.common.sms.Sample;
import com.zhengshang.common.utils.PartnerLevelUtils;
import com.zhengshang.common.utils.PromoCodeUtils;
import com.zhengshang.common.utils.SecurityUtils;
import com.zhengshang.common.utils.StringUtils;
import com.zhengshang.security.service.AppUserLoginService;
import com.zhengshang.security.service.SmsService;
import com.zhengshang.security.service.TokenService;
import com.zhengshang.system.service.ISysConfigService;
import com.zhengshang.system.service.ISysRoleService;
import com.zhengshang.system.service.ISysUserService;
import com.zhengshang.third.phone.PhoneAreaUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.regex.Pattern;

/**
 * @title 登录Controller
 * @description
 * @author admin
 * @updateTime 2021/3/1 17:42
 * @throws
 */
@Api(tags = "登录模块")
@RestController
public class LoginController extends BaseController {

    @Autowired
    private AppUserLoginService loginService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private PhoneAreaUtils phoneAreaUtils;

    @ApiOperation(value = "登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "用户密码", dataType = "string", paramType = "query")
    })
    @RepeatSubmit
    @PostMapping("/login")
    public AjaxResult login(
            @RequestParam String username,
            @RequestParam String password,
            HttpServletRequest request, HttpServletResponse response){

        String token = loginService.login(username, password);
        LoginAppUser loginAppUser = tokenService.getLoginAppUser(token);
        loginAppUser.getAppUser().setToken(token);
        if (StringUtils.isNotBlank(loginAppUser.getAppUser().getAvatar()) && loginAppUser.getAppUser().getAvatar().indexOf("https://") == -1) {
            loginAppUser.getAppUser().setAvatar(configService.selectConfigByKey("sys.oss.file.header") + loginAppUser.getAppUser().getAvatar());
        }
        SysUser user = new SysUser();
        user.setUserType(UserConstants.USER_TYPE_APP);
        user.setUpUserId(loginAppUser.getAppUser().getUserId());
        user.setUpUpUserId(loginAppUser.getAppUser().getUserId());
        loginAppUser.getAppUser().setTeamNum(userService.queryMyTeamNum(user));
        loginAppUser.getAppUser().setPartnerLevel(PartnerLevelUtils.getLevel(loginAppUser.getAppUser().getContributionValue()));
        logger.info("登录成功");
        return AjaxResult.success(loginAppUser.getAppUser());
    }

    @ApiOperation(value = "注册")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phonenumber", value = "手机号", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "promoCode", value = "推广码", required = false, dataType = "string", paramType = "query")
    })
    @RepeatSubmit
    @PostMapping("/register")
    public AjaxResult register(
            @RequestParam String phonenumber,
            @RequestParam String code,
            @RequestParam(required = false) String promoCode,
            HttpServletRequest request, HttpServletResponse response) {
        if (StringUtils.isBlank(phonenumber) || StringUtils.isBlank(code)) {
            return AjaxResult.error("参数异常");
        }
        SysUser appUser = new SysUser();
        appUser.setPhonenumber(phonenumber);
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(appUser))) {
            return AjaxResult.error("该手机号已存在");
        }

        //校验验证码
        String verificationCode = smsService.getCode(phonenumber);
        if (StringUtils.isBlank(verificationCode)) {
            return AjaxResult.error("验证码已失效");
        }
        if (!verificationCode.equals(code)) {
            return AjaxResult.error("验证码错误");
        }

        if (StringUtils.isNotBlank(promoCode)) {
            //根据推广码绑定上级推广用户
            SysUser upUser = userService.getUserByPromoCode(promoCode);
            if (upUser == null) {
                return AjaxResult.error("推广码错误");
            }
            appUser.setUpUserId(upUser.getUserId());
            appUser.setUpUpUserId(upUser.getUpUserId());
            appUser.setAllSuperiorUserIds(upUser.getAllSuperiorUserIds() + ",'" + upUser.getUserId() + "'");
        } else {
            //如果不填写邀请码，固定父级账号
            String defaultParentAccount = configService.selectConfigByKey("app.default.parent.account");
            defaultParentAccount = StringUtils.isBlank(defaultParentAccount) ? AppConstant.DEFAULT_PARENT_ACCOUNT : defaultParentAccount;
            SysUser upUesr = userService.selectUserByUserName(defaultParentAccount);
            appUser.setUpUserId(upUesr.getUserId());
            appUser.setAllSuperiorUserIds("'" + upUesr.getUserId() + "'");
        }
        appUser.setDelFlag(UserStatus.OK.getCode());
        appUser.setUserName(phonenumber);
        appUser.setUserType(UserConstants.USER_TYPE_APP);
        appUser.setNickName(phonenumber);
        appUser.setSignCount(0);
        appUser.setCouponCount(0);
        appUser.setAppMemberType(UserConstants.APP_MEMBER_TYPE_TOURIST);
        String defaultPwd = configService.selectConfigByKey("sys.user.initPassword");
        appUser.setPassword(SecurityUtils.encryptPassword(defaultPwd));
        appUser.setPromoCode(getPromoCode());
        //绑定角色（会员）
        SysRole touristRole = roleService.getRoleByKey("mem_tourist");
        if (touristRole != null) {
            appUser.setRoleIds(new Long[]{ touristRole.getRoleId()});
        }
        userService.insertUser(appUser);
        //使用过后删除验证码
        smsService.deleteCode(phonenumber);
        //生成归属地记录
        phoneAreaUtils.getPhoneInfo(phonenumber);
        return AjaxResult.success();
    }

    @ApiOperation(value = "获取验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "string", paramType = "query")
    })
    @Log(title = "获取验证码", businessType = BusinessType.OTHER)
    @PostMapping("/getVerificationCode")
    @RepeatSubmit
    public AjaxResult getVerificationCode(
            @RequestParam String phone,
            HttpServletRequest request, HttpServletResponse response) {
        if (!validateMobilePhone(phone)) {
            return AjaxResult.error("请输入正确的手机号");
        }
        String code = smsService.createCode(phone);
        try {
            //发送短信
            Sample.sendSms(phone, code);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("短信发送失败");
        }
        logger.info("手机号<{}>获取验证码成功，验证码为：{}", phone, code);
        return AjaxResult.success("获取验证码成功");
    }

    /**
     * @title 修改密码
     * @description
     * @author admin
     * @updateTime 2020/12/7 17:58
     * @throws
     */
    @ApiOperation(value = "忘记密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "newPassword", value = "新密码", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "confirmPassword", value = "确认密码", dataType = "String", paramType = "query")
    })
    @PostMapping("/forgetPwd")
    public AjaxResult forgetPwd(
            @RequestParam String phone,
            @RequestParam String code,
            @RequestParam String newPassword,
            @RequestParam String confirmPassword,
            HttpServletRequest request, HttpServletResponse response){

        try {
            if (StringUtils.isBlank(phone) || StringUtils.isBlank(code) || StringUtils.isBlank(newPassword) || StringUtils.isBlank(confirmPassword)) {
                return AjaxResult.error("参数异常");
            }
            if (!newPassword.equals(confirmPassword)) {
                return AjaxResult.error("两次密码不一致！");
            }
            //校验验证码
            String verificationCode = smsService.getCode(phone);
            if (StringUtils.isBlank(verificationCode)) {
                return AjaxResult.error("验证码已失效");
            }
            if (!verificationCode.equals(code)) {
                return AjaxResult.error("验证码错误");
            }

            //如果登录，删除token
            SysUser user = userService.selectUserByUserName(phone);
            if (user == null) {
                return AjaxResult.error("该手机号还未注册！");
            }
            String tokenKey = tokenService.getValue(tokenService.getAppUserIdKey(user.getUserId()));
            if (StringUtils.isNotBlank(tokenKey)) {
                tokenService.delLoginAppUser(tokenKey, user.getUserId());
            }

            //修改用户密码
            String newPwd = SecurityUtils.encryptPassword(newPassword);
            userService.resetUserPwd(user.getUserName(), newPwd);
            logger.info("用户<" + user.getUserName() + ">密码修改成功");
            //使用过后删除验证码
            smsService.deleteCode(phone);

            //TODO 发送消息通知(1系统通知，2短信通知)
            return AjaxResult.success("修改成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("密码修改失败，请稍后再试或联系管理员");
        }
    }

    /**
     *  正则：手机号（简单校验）, 1字头＋10位数字即可.
     * @param in
     * @return
     */
    private static boolean validateMobilePhone(String in) {
        if (StringUtils.isBlank(in)) {
            return false;
        }
        Pattern pattern = Pattern.compile("^[1]\\d{10}$");
        return pattern.matcher(in).matches();
    }

    /**
     * @title 递归获取推广码（保证不重复）
     * @description 
     * @author admin 
     * @updateTime 2021/3/3 15:23 
     * @throws
     */
    private String getPromoCode() {
        String promoCode = PromoCodeUtils.getPromoCode();
        if (userService.getUserByPromoCode(promoCode) != null) {
            return getPromoCode();
        }
        return promoCode;
    }

}
